package net.yxsoft.controller.common.interceptor;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import net.yxsoft.controller.common.ApiBaseController;
import net.yxsoft.kit.Sm3Utils;
import net.yxsoft.service.common.ApiService;

import java.util.Arrays;
import java.util.Map;

public class ApiPkInterceptor implements Interceptor {

  /**
   * api 的有效时间，默认为 10 分钟
   */
  private static final long TIMEOUT = 10 * 60 * 1000;

  @Override
  public void intercept(Invocation inv) {

    ApiBaseController controller = (ApiBaseController)inv.getController();

    Map<String, String[]> params = controller.getParaMap();

    if(null == params && params.size() == 0){
      inv.getController().renderJson(Ret.fail().set("message", "参数异常。"));
      return;
    }

    String publicKey = String.valueOf(params.get("publicKey"));
    String sign = String.valueOf(params.get("sign"));
    String timeStr = String.valueOf(params.get("timestamp"));



    if (StrKit.isBlank(publicKey) ) {

      inv.getController().renderJson(Ret.fail().set("message", "在请求参数中未获取到publicKey内容，请注意请求参数是否正确。"));
      return;
    }

    if (StrKit.isBlank(sign)) {

      inv.getController().renderJson(Ret.fail("message", "签名数据不能为空，请提交 sign 数据。"));
      return;
    }

    System.out.println("时间戳:" + timeStr);

    Long time = timeStr == null || "null".equals(timeStr) ? null : Long.valueOf(timeStr);
    if (time == null) {
      inv.getController().renderJson(Ret.fail("message", "时间参数不能为空，请提交 timestamp 参数数据。"));
      return;
    }

   // 时间验证，可以防止重放攻击
    if (Math.abs(System.currentTimeMillis() - time) > TIMEOUT) {

      inv.getController().renderJson(Ret.fail("message", "请求超时，请重新请求。"));
      return;
    }

    String localSign = createLocalSign(params);
    if (sign.equals(localSign) == false) {
      inv.getController().renderJson(Ret.fail().set("message", "数据签名错误。"));
      return;
    }



    /**
     * 记录接口访问次数

    ApiViewService.me.processApiView(inv.getActionKey(), appId);
     */
    inv.invoke();
  }

  private String createLocalSign(Map<String, String[]> params) {



    String privatekey =ApiService.me.getPrivateKeyInfo(String.valueOf(params.get("publicKey")));
    if(StrKit.isBlank(privatekey)){
      return "";
    }

    String[] keys = params.keySet().toArray(new String[0]);
    Arrays.sort(keys);
    StringBuilder query = new StringBuilder();
    for (String key : keys) {
      if ("sign".equals(key)) {
        continue;
      }

      String value = String.valueOf(params.get(key));
      query.append(key).append("=").append(value).append("&");
    }
    query.append(privatekey);

    return Sm3Utils.encrypt(query.toString()).toUpperCase();

  }

}
